#include "MainFrame.h"
#include "SerialPort.h"
#include <QTabWidget>
#include <QDebug>
#include <QGridLayout>
#include <QPushButton>
#include <QMenuBar>
#include <QMenu>
#include <QLabel>
#include <QDialog>
#include <QMessageBox>
#include <QDateTime>
#include <QFileInfo>

MainFrame::MainFrame(QWidget *parent) : QWidget(parent)
{
    m_tabWgt = new QTabWidget(this);
    m_tabWgt->setTabsClosable(true);
    m_tabWgt->setMovable(true);
    QMenuBar *menuBar = createMenuBar();

    QGridLayout *layoutSurface = new QGridLayout(this);
    layoutSurface->setMargin(0);
    layoutSurface->setSpacing(0);
    layoutSurface->addWidget(menuBar, 0, 0);
    layoutSurface->addWidget(m_tabWgt, 2, 0);

    connect(m_tabWgt, &QTabWidget::tabCloseRequested, this, [=](int index){
        m_tabWgt->widget(index)->deleteLater();
        m_tabWgt->removeTab(index);
    });

    createSerialPortWidget();

    m_stWgt = new StartWidget();
    m_stWgt->setDisabled(true);
    connect(m_stWgt, &StartWidget::signalBeginReboot, this, &MainFrame::slot_rebootBegin);
    connect(m_stWgt, &StartWidget::signalEndReboot, this, &MainFrame::slot_rebootEnd);
    connect(this, &MainFrame::signal_rebootEnd, m_stWgt, &StartWidget::on_pushButton_end_clicked);
    //m_stWgt->show();
}

QMenuBar* MainFrame::createMenuBar()
{
    QMenu *menuNew = new QMenu("Setting", this);
    //menuNew->addAction("New Serial Port", this, &MainFrame::createSerialPortWidget);
    //menuNew->addSeparator();
    menuNew->addAction("Camera", this, &MainFrame::openCameraSetting);
    menuNew->addSeparator();
    menuNew->addAction("Quit", this, &MainFrame::close);

#if 1 /*Reboot Assist*/
    QMenu *menuStart = new QMenu("Start", this);
    menuStart->addAction("RebootScript", this, &MainFrame::openStartWidget);
#endif

    QMenu *menuAbout = new QMenu("About", this);
    menuAbout->addAction("About Assist", this, &MainFrame::aboutXTTool);

    QMenuBar *menuBar = new QMenuBar(this);
    menuBar->addMenu(menuNew);
    menuBar->addMenu(menuStart);
    menuBar->addMenu(menuAbout);
    return menuBar;
}

QString MainFrame::getNewWidgetName(int i)
{
    static int index[5] = {0};
    return QString("-%1").arg(index[i]++);
}

void MainFrame::createSerialPortWidget()
{
    tmpWgt = new SerialPort(this);
    m_tabWgt->addTab(tmpWgt, "serial"+getNewWidgetName(0));
    m_tabWgt->setCurrentWidget(tmpWgt);

    connect(tmpWgt, &SerialPort::signalUpdateTitle, this, [=](QString text){
        QWidget *wgt = qobject_cast<QWidget*>(sender());
        m_tabWgt->tabBar()->setTabText(m_tabWgt->indexOf(wgt), text);
    });

    connect(tmpWgt, &SerialPort::signalOpenSerial, this, &MainFrame::slot_serialOpen);
    connect(tmpWgt, &SerialPort::signalCloseSerial, this, &MainFrame::slot_serialClose);
}

void MainFrame::openStartWidget()
{
    this->m_stWgt->show();
}

void MainFrame::openCameraSetting()
{
    this->m_stWgt->camera->show();
}

void MainFrame::aboutXTTool()
{
    QLabel lb;
    lb.setWordWrap(true);
    lb.setText("HBW Reboot Assist V1.b.1\r\n\r\nA tool contains Serial Port.\r\n");

    QDialog *dlg = new QDialog(this);
    dlg->setWindowTitle("About Assist");
    dlg->setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
    dlg->setFixedSize(400, 200);

    QGridLayout *gl = new QGridLayout(dlg);
    gl->addWidget(&lb);
    dlg->exec();

    dlg->deleteLater();
    gl->deleteLater();
}

int MainFrame::RebootInit()
{
    QMessageBox msgBox;
    msgBox.setWindowTitle("Error!");
    msgBox.setIcon(QMessageBox::Critical);
    msgBox.resize(400, 200);

    /*检查日志路径是否存在*/
    QFileInfo fileInfo(m_stWgt->get_savingPath());
    //qDebug() << "Saving Path = " << m_stWgt->saveingPath;
    if(!fileInfo.exists())
    {
        msgBox.setText("Saving Path Not Exist --- \"" + m_stWgt->get_savingPath() + "\"");
        msgBox.exec();
        return -1;
    }

    /*检查摄像头是否可用*/
    if(m_stWgt->useCamera)
    {
        /*加入摄像头可用的判断条件*/
        if(0)
        {
            msgBox.setText("Camera is something error");
            msgBox.exec();
            return -1;
        }
    }

    return 0;
}

void MainFrame::slot_serialOpen()
{
    m_stWgt->setEnabled(true);
}

void MainFrame::slot_serialClose()
{
    tmpWgt->RebootRunning = false;
    emit signal_rebootEnd();
    m_stWgt->setEnabled(false);
}

void MainFrame::slot_rebootBegin()
{
    if (RebootInit() < 0)
    {
        emit signal_rebootEnd();
        return;
    }

    tmpWgt->RebootRunning = true;
    RebootLoop();
}

void MainFrame::slot_rebootEnd()
{
    tmpWgt->RebootRunning = false;
}

int MainFrame::RebootLoop()
{
    int ret;
    QMessageBox msgBox_done;
    QMessageBox msgBox_err;

    msgBox_done.setWindowTitle("Finish!");
    msgBox_done.resize(400, 200);
    msgBox_err.setWindowTitle("Error!");
    msgBox_err.setIcon(QMessageBox::Critical);
    msgBox_err.resize(400, 200);

    qDebug() << "Reboot Begin";
    tmpWgt->sendStr(QString("\r"));
    emit m_stWgt->slot_setRemainNum();
    emit m_stWgt->camera->signal_videoBegin();

    /*开始循环*/
    while(m_stWgt->RemainRebootTimes > 0 && tmpWgt->RebootRunning == true)
    {
        //qDebug() << "time remain: " << m_stWgt->RemainRebootTimes;
        m_stWgt->RemainRebootTimes--;
        emit m_stWgt->slot_setRemainNum();

        ret = tmpWgt->waitForStrings(m_stWgt->get_strWaitFor1(), 200);
        //qDebug() << "Ret = " << ret;
        switch (ret) {
        case 4:
        case 5:
            if(m_stWgt->useCamera)
            {
                /*Add Opencv Condition Judge*/
                if(m_stWgt->camera->videoCaptureInit() < 0)
                {
                    msgBox_err.setText("VideoCapture init failed");
                    goto LOOPEND;
                }

                if(!m_stWgt->camera->isEnterDesktop(m_stWgt->camera->capture))
                {
                    msgBox_err.setText("Not Enter Desktop");
                    goto LOOPEND;
                }
                cv::destroyAllWindows();
            }

            tmpWgt->rebootSystem(m_stWgt->get_keyWord(), m_stWgt->get_userName(), m_stWgt->get_passWord());
            tmpWgt->slot_cleanLog();
            if(m_stWgt->useCamera)
            {
                m_stWgt->camera->cacheDelete();
            }
            break;
        default:
            goto LOOPEND;
        }

        /*最后一次循环*/
        if(m_stWgt->RemainRebootTimes == 0)
        {
            ret = tmpWgt->waitForStrings(m_stWgt->get_strWaitFor1(), 100);
            switch (ret) {
            case 4:
            case 5:{
                if(m_stWgt->useCamera)
                {
                    /*Add Opencv Condition Judge*/
                    if(!m_stWgt->camera->isEnterDesktop(m_stWgt->camera->capture))
                    {
                        msgBox_err.setText("Not Enter Desktop");
                        goto LOOPEND;
                    }
                    cv::destroyAllWindows();
                }

                if(m_stWgt->useCamera)
                {
                    if(!m_stWgt->camera->cacheDelete())
                    {
                        msgBox_err.setText("Cannot delete cache video");
                        goto LOOPEND;
                    }
                }
                msgBox_done.setText("Test " + QString::number(m_stWgt->get_rebootTimes()) + "times Success!");
                msgBox_done.exec();

                break;
            }
            default:
                msgBox_err.setText("Reboot Error " + QString::number(m_stWgt->get_rebootTimes() - m_stWgt->RemainRebootTimes) + "th");
                goto LOOPEND;
            }
        }
        m_stWgt->camera->capture.release(); //重新打开清除缓存
    }

    emit signal_rebootEnd();
    tmpWgt->RebootRunning = false;
    return ret;

LOOPEND:
    msgBox_err.setText("Reboot Error " + QString::number(m_stWgt->RemainRebootTimes) + "th");
    tmpWgt->RebootRunning = false;
    QDateTime currentTime = QDateTime::currentDateTime();
    /*保存日志和录像*/
    tmpWgt->slot_saveLog(QString(m_stWgt->get_savingPath() + "/" + currentTime.toString("yyyy_M_d_HH_mm_ss_") + QString::number(m_stWgt->get_rebootTimes() - m_stWgt->RemainRebootTimes) + "th_failed.log"));
    if(m_stWgt->useCamera)
    {
        //转存录像
        m_stWgt->camera->cacheSaving(currentTime.toString("yyyy_M_d_HH_mm_ss_").toStdString() + "failed.avi");
    }
    cv::destroyAllWindows();
    emit signal_rebootEnd();
    msgBox_err.exec();
    return ret;
}
